﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HappyFrogXna.Roles;
using HappyFrogXna.ScreenSystem;
using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
using Microsoft.Xna.Framework.Media;
using HappyFrogXna.DrawingSystem;
using System.Diagnostics;
using HappyFrogXna.Miscellaneous;
using HappyFrogXna.Level;
using HappyFrogXna.ParticleSystem;
using HappyFrogXna.Scene;

namespace HappyFrogXna
{
    delegate void MoveCameraDelegate(float value);

    /// <summary>
    /// a controller use for bulid game scene
    /// </summary>
    class SceneBuildController
    {
        Camera2D _camera;
        public MoveCameraDelegate MoveLeft;
        public MoveCameraDelegate MoveRight;

        World _world;
        EntityAssemble _entities;

        EntityComponentSelector _selector;
        Entity _entityDragged = null;
        Entity _entityMoved = null;

        IScene _scene;
        private bool _isDraggingEntity = false;
        private bool _isMovingEntity = false;

        public SceneBuildController(World w, Camera2D c)
        {
            _world = w;
            _camera = c;
        }

        internal void LoadContent()
        {
            _entities = new EntityAssemble();
            _scene = SceneCreator.CreateScene("BasicScene", _world);

            _selector = new EntityComponentSelector(_world, _camera,
                this.SetDraggingEntity, this.BeginDrawingDelegateWithCamera, this.BeginDrawingDelegateWithoutCamera, this.EndDrawing);

            _selector.LoadContent();

            _camera.MinPosition = new Vector2(ScreenInfo.ScreenSize.Width / 2, ScreenInfo.ScreenSize.Height / 2);
            _camera.MaxPosition = new Vector2(_scene.GroundWidthInDisplay - ScreenInfo.ScreenSize.Width / 2, ScreenInfo.ScreenSize.Height / 2);
            _camera.Position = _camera.MinPosition;
            _camera.Jump2Target();
            Debug.WriteLine("## camera begin: " + _camera.MinPosition + " " + _camera.MaxPosition);
        }

        public void SetDraggingEntity(Entity e)
        {
            _entityDragged = e;
        }

        private void printOutScene()
        {
            Debug.WriteLine("    public void EnterLevel(out EntityAssemble entities)\n    {");
            Debug.WriteLine("        List<Entity> frogs = new List<Entity>();");
            Debug.WriteLine("        List<Entity> objects = new List<Entity>();");
            Debug.WriteLine("        List<Entity> animals = new List<Entity>();");
            Debug.WriteLine("");
            if (_entities.Frogs.Count < 1)
            {
                Debug.WriteLine("    Need at least one frog !\n\n    }");
                return;
            }
            Debug.WriteLine("        frogs.Add(new " + _entities.Frogs[0].UserDate.Name + "(_world, new Vector2(_scene.SlingshotCenterPos.X, _scene.SlingshotCenterPos.Y)));");
            Debug.WriteLine("        frogs[0].Rotation = 0.0f;");
            Debug.WriteLine("        frogs[0].IsActive = false;");
            Debug.WriteLine("        frogs[0].IsVisible = true;");
            for (int i = 1; i < _entities.Frogs.Count; ++i)
            {
                Debug.WriteLine("        frogs.Add(new " + _entities.Frogs[i].UserDate.Name + "(_world, new Vector2(" + _entities.Frogs[i].Position.X + "f, " + _entities.Frogs[i].Position.Y + "f)));");
                Debug.WriteLine("        frogs[" + i + "].Rotation = 0.0f;");
                Debug.WriteLine("        frogs[" + i + "].IsActive = false;");
                Debug.WriteLine("        frogs[" + i + "].IsVisible = true;");
            }
            Debug.WriteLine("recodeFrogStartPos(frogs);\n");
            for (int i = 0; i < _entities.Objects.Count; ++i)
            {
                Debug.WriteLine("        objects.Add(new " + _entities.Objects[i].UserDate.Name + "(_world, new Vector2(" + _entities.Objects[i].Position.X + "f, " + _entities.Objects[i].Position.Y + "f)));");
                Debug.WriteLine("        objects[" + i + "].Rotation = " + _entities.Objects[i].Rotation +"f;");
                Debug.WriteLine("        objects[" + i + "].IsActive = true;");
                Debug.WriteLine("        objects[" + i + "].IsVisible = true;");
            }
            Debug.WriteLine("");
            for (int i = 0; i < _entities.Animals.Count; ++i)
            {
                Debug.WriteLine("        animals.Add(new " + _entities.Animals[i].UserDate.Name + "(_world, new Vector2(" + _entities.Animals[i].Position.X + "f, " + _entities.Animals[i].Position.Y + "f)));");
                Debug.WriteLine("        animals[" + i + "].Rotation = " + _entities.Animals[i].Rotation + "f;");
                Debug.WriteLine("        animals[" + i + "].IsActive = true;");
                Debug.WriteLine("        animals[" + i + "].IsVisible = true;");
            }
            Debug.WriteLine("");
            Debug.WriteLine("        entities = new EntityAssemble(frogs, objects, animals);");
            Debug.WriteLine("    }");
        }

        internal bool HandleInput(ScreenSystem.InputHelper input, Microsoft.Xna.Framework.GameTime gameTime)
        {
            if (input.IsNewKeyPress(Keys.A))
            {
                printOutScene();
            }

            Vector2 position = _camera.ConvertScreenToWorld(input.Cursor);
            bool handled = _selector.IsTouchedTopView(position);

            if (_entityDragged != null)
            {
                if (input.IsNewMouseButtonRelease(MouseButtons.LeftButton))
                {
                    _entityDragged.IsActive = true;
                    _entityDragged.IsVisible = true;
                    if (_entityDragged.UserDate.Type == EntityType.Animal)
                    {
                        _entities.Animals.Add(_entityDragged);
                    }
                    else if (_entityDragged.UserDate.Type == EntityType.Frog)
                    {
                        _entities.Frogs.Add(_entityDragged);
                    }
                    else
                    {
                        _entities.Objects.Add(_entityDragged);
                    }
                    _entityDragged = null;
                    _isDraggingEntity = false;
                }
                else
                {
                    _entityDragged.Position = position;
                    _isDraggingEntity = true;
                }
            }

            if (!_isMovingEntity && input.IsNewMouseButtonPress(MouseButtons.LeftButton))
            {
                Entity entityTouched = _entities.TestTouchedEntity(position);
                if (entityTouched != null)
                {
                    _entityMoved = entityTouched;
                    _entityMoved.IsActive = false;
                    _isMovingEntity = true;
                    handled = true;
                }
            }

            if (_isMovingEntity)
            {
                //Debug.WriteLine("## cursor: " + position.X + " , camera: " +  ConvertUnits.ToSimUnits(_camera.Position.X) + " , screen: " + ConvertUnits.ToSimUnits(ScreenInfo.ScreenSize.Width / 2));
                _entityMoved.Position = position;
                if (input.IsNewMouseButtonRelease(MouseButtons.LeftButton))
                {
                    _entityMoved.IsActive = true;
                    _entityMoved.Body.Awake = true;
                    _entityMoved = null;
                    _isMovingEntity = false;
                }
                else if (position.X < ConvertUnits.ToSimUnits(_camera.Position.X - ScreenInfo.ScreenSize.Width / 2) + 5)
                {
                    MoveLeft(50f);
                }
                else if (position.X > ConvertUnits.ToSimUnits(_camera.Position.X + ScreenInfo.ScreenSize.Width / 2) - 5)
                {
                    MoveRight(50f);
                }
            }

            _selector.HandleInput(input);

            return handled;
        }

        internal void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            _selector.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }

        internal void EndDrawing()
        {
            GolbalXnaGadgetProvider.Instance.SpriteBatch.End();
        }

        internal void BeginDrawingDelegateWithCamera()
        {
            GolbalXnaGadgetProvider.Instance.SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, _camera.View);
        }

        internal void BeginDrawingDelegateWithoutCamera()
        {
            GolbalXnaGadgetProvider.Instance.SpriteBatch.Begin();
        }

        internal void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            GolbalXnaGadgetProvider.Instance.GraphicsDevice.Clear(_scene.BackgroundColor);

            GolbalXnaGadgetProvider.Instance.SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, _camera.View);

            _scene.Draw();

            if (_isDraggingEntity)
            {
                GolbalXnaGadgetProvider.Instance.SpriteBatch.Draw(_entityDragged.Texture, ConvertUnits.ToDisplayUnits(_entityDragged.Position), null,
                    Color.White, _entityDragged.Rotation, _entityDragged.EntitySprite.Origin, _entityDragged.ScaleRadioDisplayOnScreen, SpriteEffects.None, 0.5f);
            }

            // Draw frogs
            for (int i = 0; i < _entities.Frogs.Count; ++i)
            {
                if (_entities.Frogs[i].IsVisible)
                {
                    GolbalXnaGadgetProvider.Instance.SpriteBatch.Draw(_entities.Frogs[i].Texture, ConvertUnits.ToDisplayUnits(_entities.Frogs[i].Position), null,
                        Color.White, _entities.Frogs[i].Rotation, _entities.Frogs[i].EntitySprite.Origin, _entities.Frogs[i].ScaleRadioDisplayOnScreen, SpriteEffects.None, 0.5f);
                }
            }

            // Draw objects
            for (int i = 0; i < _entities.Objects.Count; ++i)
            {
                if (_entities.Objects[i].IsVisible)
                {
                    GolbalXnaGadgetProvider.Instance.SpriteBatch.Draw(_entities.Objects[i].Texture, ConvertUnits.ToDisplayUnits(_entities.Objects[i].Position), null,
                        Color.White, _entities.Objects[i].Rotation, _entities.Objects[i].EntitySprite.Origin, _entities.Objects[i].ScaleRadioDisplayOnScreen, SpriteEffects.None, 0.5f);
                }
            }

            // Draw animals
            for (int i = 0; i < _entities.Animals.Count; ++i)
            {
                if (_entities.Animals[i].IsVisible)
                {
                    GolbalXnaGadgetProvider.Instance.SpriteBatch.Draw(_entities.Animals[i].Texture, ConvertUnits.ToDisplayUnits(_entities.Animals[i].Position), null,
                        Color.White, _entities.Animals[i].Rotation, _entities.Animals[i].EntitySprite.Origin, _entities.Animals[i].ScaleRadioDisplayOnScreen, SpriteEffects.None, 0.5f);
                }
            }

            _selector.Draw(gameTime);

            GolbalXnaGadgetProvider.Instance.SpriteBatch.End();
        }
    }
}
